package org.gdstash.character;

import org.gdstash.file.GDReader;
import org.gdstash.file.GDWriter;
import org.gdstash.item.GDAbstractContainer;
import org.gdstash.item.GDItem;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

public class GDCharEquippedContainer extends GDAbstractContainer {
    private GDItem[] equipment;
    private GDItem[] weapon1;
    private GDItem[] weapon2;
    private GDItem[] removedEquipment;
    private GDItem[] removedWeapon1;
    private GDItem[] removedWeapon2;
    private byte useAlternate;
    private byte alternate1;
    private byte alternate2;
    private GDChar gdc;

    public GDCharEquippedContainer(final GDChar gdc) {
        super(6);
        this.equipment = new GDItem[12];
        this.weapon1 = new GDItem[2];
        this.weapon2 = new GDItem[2];
        this.removedEquipment = new GDItem[this.equipment.length];
        this.removedWeapon1 = new GDItem[this.weapon1.length];
        this.removedWeapon2 = new GDItem[this.weapon2.length];
        this.gdc = gdc;
    }

    @Override
    public List<GDItem> getItemList() {
        final List<GDItem> list = new LinkedList<GDItem>();
        for (int i = 0; i < this.equipment.length; ++i) {
            if (this.equipment[i] != null) {
                final GDItem item = this.equipment[i];
                if (item.getItemID() != null) {
                    item.setX(0);
                    item.setY(i);
                    list.add(item);
                }
            }
        }
        for (int i = 0; i < this.weapon1.length; ++i) {
            if (this.weapon1[i] != null) {
                final GDItem item = this.weapon1[i];
                if (item.getItemID() != null) {
                    item.setX(1);
                    item.setY(i);
                    list.add(item);
                }
            }
        }
        for (int i = 0; i < this.weapon2.length; ++i) {
            if (this.weapon2[i] != null) {
                final GDItem item = this.weapon2[i];
                if (item.getItemID() != null) {
                    item.setX(2);
                    item.setY(i);
                    list.add(item);
                }
            }
        }
        return list;
    }

    @Override
    public boolean addItem(final GDItem item) {
        if (!this.canAddItem(item)) {
            return false;
        }
        final int x = item.getX();
        final int y = item.getY();
        switch (x) {
            case 0: {
                this.equipment[y] = item;
                break;
            }
            case 1: {
                this.weapon1[y] = item;
                break;
            }
            case 2: {
                this.weapon2[y] = item;
                break;
            }
        }
        return this.changed = true;
    }

    @Override
    public boolean removeItem(final GDItem item) {
        boolean found = false;
        final int x = item.getX();
        final int y = item.getY();
        switch (x) {
            case 0: {
                if (this.equipment.length > y && this.equipment[y] == item) {
                    (this.equipment[y] = new GDItem(this.gdc.getCharName(), this.gdc.isHardcore(), 6)).setX(x);
                    this.equipment[y].setY(y);
                    found = true;
                    break;
                }
                break;
            }
            case 1: {
                if (this.weapon1.length > y && this.weapon1[y] == item) {
                    (this.weapon1[y] = new GDItem(this.gdc.getCharName(), this.gdc.isHardcore(), 6)).setX(x);
                    this.weapon1[y].setY(y);
                    found = true;
                    break;
                }
                break;
            }
            case 2: {
                if (this.weapon2.length > y && this.weapon2[y] == item) {
                    (this.weapon2[y] = new GDItem(this.gdc.getCharName(), this.gdc.isHardcore(), 6)).setX(x);
                    this.weapon2[y].setY(y);
                    found = true;
                    break;
                }
                break;
            }
        }
        if (found) {
            this.changed = true;
        }
        return found;
    }

    private boolean canAddItem(final GDItem item) {
        final int x = item.getX();
        final int y = item.getY();
        boolean possible = false;
        if (x == 0) {
            switch (y) {
                case 0: {
                    if (this.equipment[0].getItemID() == null && item.getItemClass().equals("ArmorProtective_Head")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 1: {
                    if (this.equipment[1].getItemID() == null && item.getItemClass().equals("ArmorJewelry_Amulet")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 2: {
                    if (this.equipment[2].getItemID() == null && item.getItemClass().equals("ArmorProtective_Chest")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 3: {
                    if (this.equipment[3].getItemID() == null && item.getItemClass().equals("ArmorProtective_Legs")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 4: {
                    if (this.equipment[4].getItemID() == null && item.getItemClass().equals("ArmorProtective_Feet")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 5: {
                    if (this.equipment[5].getItemID() == null && item.getItemClass().equals("ArmorProtective_Hands")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 6: {
                    if (this.equipment[6].getItemID() == null && item.getItemClass().equals("ArmorJewelry_Ring")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 7: {
                    if (this.equipment[7].getItemID() == null && item.getItemClass().equals("ArmorJewelry_Ring")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 8: {
                    if (this.equipment[8].getItemID() == null && item.getItemClass().equals("ArmorProtective_Waist")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 9: {
                    if (this.equipment[9].getItemID() == null && item.getItemClass().equals("ArmorProtective_Shoulders")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 10: {
                    if (this.equipment[10].getItemID() == null && item.getItemClass().equals("ArmorJewelry_Medal")) {
                        possible = true;
                        break;
                    }
                    break;
                }
                case 11: {
                    if (this.equipment[11].getItemID() == null && item.getItemClass().equals("ItemArtifact")) {
                        possible = true;
                        break;
                    }
                    break;
                }
            }
        }
        if (x == 1) {
            switch (y) {
                case 0: {
                    if (this.weapon1[0].getItemID() != null) {
                        break;
                    }
                    if (item.is1HWeapon()) {
                        possible = true;
                    }
                    if (item.is2HWeapon()) {
                        final GDItem gdi = this.weapon1[1];
                        if (gdi == null || gdi.getItemID() == null) {
                            possible = true;
                        }
                        break;
                    }
                    break;
                }
                case 1: {
                    if (this.weapon1[1].getItemID() != null || (!item.is1HWeapon() && !item.isOffhand())) {
                        break;
                    }
                    final GDItem gdi = this.weapon1[0];
                    if (gdi == null || gdi.getItemID() == null) {
                        possible = true;
                        break;
                    }
                    if (gdi.is1HWeapon()) {
                        possible = true;
                        break;
                    }
                    break;
                }
            }
        }
        if (x == 2) {
            switch (y) {
                case 0: {
                    if (this.weapon2[0].getItemID() != null) {
                        break;
                    }
                    if (item.is1HWeapon()) {
                        possible = true;
                    }
                    if (item.is2HWeapon()) {
                        final GDItem gdi = this.weapon2[1];
                        if (gdi == null || gdi.getItemID() == null) {
                            possible = true;
                        }
                        break;
                    }
                    break;
                }
                case 1: {
                    if (this.weapon2[1].getItemID() != null || (!item.is1HWeapon() && !item.isOffhand())) {
                        break;
                    }
                    final GDItem gdi = this.weapon2[0];
                    if (gdi == null || gdi.getItemID() == null) {
                        possible = true;
                        break;
                    }
                    if (gdi.is1HWeapon()) {
                        possible = true;
                        break;
                    }
                    break;
                }
            }
        }
        return possible;
    }

    public void read(final int version) throws IOException {
        this.useAlternate = GDReader.readEncByte();
        for (int i = 0; i < this.equipment.length; ++i) {
            GDItem item = new GDItem(this.gdc.getCharName(), this.gdc.isHardcore(), 6);
            item.read(version);
            if (item.hasErrors()) {
                this.removedEquipment[i] = item;
                item = new GDItem(this.gdc.getCharName(), this.gdc.isHardcore(), 6);
            } else {
                this.removedEquipment[i] = null;
            }
            this.equipment[i] = item;
        }
        this.alternate1 = GDReader.readEncByte();
        for (int i = 0; i < this.weapon1.length; ++i) {
            GDItem item = new GDItem(this.gdc.getCharName(), this.gdc.isHardcore(), 6);
            item.read(version);
            if (item.hasErrors()) {
                this.removedWeapon1[i] = item;
                item = new GDItem(this.gdc.getCharName(), this.gdc.isHardcore(), 6);
            } else {
                this.removedWeapon1[i] = null;
            }
            this.weapon1[i] = item;
        }
        this.alternate2 = GDReader.readEncByte();
        for (int i = 0; i < this.weapon2.length; ++i) {
            GDItem item = new GDItem(this.gdc.getCharName(), this.gdc.isHardcore(), 6);
            item.read(version);
            if (item.hasErrors()) {
                this.removedWeapon2[i] = item;
                item = new GDItem(this.gdc.getCharName(), this.gdc.isHardcore(), 6);
            } else {
                this.removedWeapon2[i] = null;
            }
            this.weapon2[i] = item;
        }
        this.changed = false;
    }

    private void mergeRemovedItems() {
        for (int i = 0; i < this.removedEquipment.length; ++i) {
            if (this.removedEquipment[i] != null) {
                this.equipment[i] = this.removedEquipment[i];
            }
        }
        for (int i = 0; i < this.removedWeapon1.length; ++i) {
            if (this.removedWeapon1[i] != null) {
                this.weapon1[i] = this.removedWeapon1[i];
            }
        }
        for (int i = 0; i < this.removedWeapon2.length; ++i) {
            if (this.removedWeapon2[i] != null) {
                this.weapon2[i] = this.removedWeapon2[i];
            }
        }
    }

    public void write(final int containerVersion) throws IOException {
        this.mergeRemovedItems();
        GDWriter.writeByte(this.useAlternate);
        for (int i = 0; i < this.equipment.length; ++i) {
            this.equipment[i].write(containerVersion);
        }
        GDWriter.writeByte(this.alternate1);
        for (int i = 0; i < this.weapon1.length; ++i) {
            this.weapon1[i].write(containerVersion);
        }
        GDWriter.writeByte(this.alternate2);
        for (int i = 0; i < this.weapon2.length; ++i) {
            this.weapon2[i].write(containerVersion);
        }
        this.changed = false;
    }

    public int getByteSize(final int containerVersion) {
        this.mergeRemovedItems();
        int size = 0;
        ++size;
        for (int i = 0; i < this.equipment.length; ++i) {
            size += this.equipment[i].getByteSize(containerVersion);
        }
        ++size;
        for (int i = 0; i < this.weapon1.length; ++i) {
            size += this.weapon1[i].getByteSize(containerVersion);
        }
        ++size;
        for (int i = 0; i < this.weapon2.length; ++i) {
            size += this.weapon2[i].getByteSize(containerVersion);
        }
        return size;
    }
}
